﻿import React, {useEffect, useRef, useState, useCallback} from 'react';
import {useSelector} from "react-redux";

interface BubbleProps {
    neonColors?: string[];
    glowIntensity?: number;
    maxBubbles?: number;
}

interface ThemeConfig {
    bubbleColors: string[];
    background: string;
}

interface CyberBubble {
    x: number;
    y: number;
    baseRadius: number;
    currentRadius: number;
    speedX: number;
    speedY: number;
    color: string;
    phase: number;
    update: (width: number, height: number) => void;
    draw: (ctx: CanvasRenderingContext2D, glow: number) => void;
    adaptColor: (colors: string[]) => void;
}

const createCyberBubble = (
    width: number,
    height: number,
    colors: string[]
): CyberBubble => {
    const baseRadius = Math.min(width, height) * 0.015;
    const currentRadius = baseRadius * (0.8 + Math.random() * 0.4);
    
    return {
        x: Math.random() * width,
        y: Math.random() * height,
        baseRadius,
        currentRadius,
        speedX: (Math.random() - 0.5),
        speedY: (Math.random() - 0.5),
        color: colors[Math.floor(Math.random() * colors.length)],
        phase: Math.random() * Math.PI * 2,
        
        update(width: number, height: number) {
            this.x += this.speedX + Math.cos(this.phase) * 0.3;
            this.y += this.speedY + Math.sin(this.phase) * 0.3;
            this.phase += 0.02;
            
            if (this.x > width + this.currentRadius) this.x = -this.currentRadius;
            if (this.x < -this.currentRadius) this.x = width + this.currentRadius;
            if (this.y > height + this.currentRadius) this.y = -this.currentRadius;
            if (this.y < -this.currentRadius) this.y = height + this.currentRadius;
            
            this.currentRadius = this.baseRadius * (0.9 + Math.sin(this.phase) * 0.1);
        },
        
        draw(ctx: CanvasRenderingContext2D, glow: number) {
            const gradient = ctx.createRadialGradient(
                this.x, this.y, 0,
                this.x, this.y, this.currentRadius
            );
            gradient.addColorStop(0, `${this.color}ff`);
            gradient.addColorStop(1, `${this.color}00`);
            
            ctx.shadowColor = this.color;
            ctx.shadowBlur = glow;
            
            ctx.beginPath();
            ctx.arc(this.x, this.y, this.currentRadius * 0.6, 0, Math.PI * 2);
            ctx.fillStyle = gradient;
            ctx.fill();
            
            ctx.beginPath();
            ctx.arc(this.x, this.y, this.currentRadius, 0, Math.PI * 2);
            ctx.strokeStyle = this.color;
            ctx.lineWidth = 2;
            ctx.stroke();
        },
        
        adaptColor(colors: string[]) {
            if (!colors.includes(this.color)) {
                this.color = colors[Math.floor(Math.random() * colors.length)];
            }
        }
    };
};

const themePresets: Record<string, ThemeConfig> = {
    dark: {
        bubbleColors: ['#FF79C6', '#8BE9FD', '#50FA7B', '#F1FA8C'], // 粉紫、天蓝、翠绿、亮黄
        background: 'rgb(28, 28, 36)' // 深灰色背景
    },
    light: {
        bubbleColors: ['#FFA500', '#FF6347', '#ADD8E6', '#FFB6C1'], // 橙色、番茄红、浅蓝、粉红
        background: 'rgb(255, 255, 250)' // 米白色背景
    }
};

const BubbleBackground: React.FC<BubbleProps> = ({
                                                     glowIntensity = 20,
                                                     maxBubbles = 40
                                                 }) => {
    const canvasRef = useRef<HTMLCanvasElement>(null);
    const bubblesRef = useRef<CyberBubble[]>([]);
    const [theme, setTheme] = useState(localStorage.getItem('mkTheme') ? 'dark' : 'light');
    const offscreenCanvas = useRef<HTMLCanvasElement>(document.createElement('canvas'));
    const offscreenCtx = useRef<CanvasRenderingContext2D | null>(null);
    const animationFrameId = useRef<number>();
    
    const initBubbles = useCallback((width: number, height: number) => {
        const density = Math.sqrt(width * height) / 100;
        const config = themePresets[theme];
        bubblesRef.current = Array.from({length: Math.min(maxBubbles, density)}, () => {
            const bubble = createCyberBubble(width, height, config.bubbleColors);
            bubble.adaptColor(config.bubbleColors);
            return bubble;
        });
    }, [theme, maxBubbles]);
    
    const animate = useCallback(() => {
        const canvas = canvasRef.current;
        const ctx = offscreenCtx.current;
        if (!canvas || !ctx) return;
        
        offscreenCanvas.current.width = canvas.width;
        offscreenCanvas.current.height = canvas.height;
        
        ctx.fillStyle = themePresets[theme].background;
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        
        bubblesRef.current.forEach(bubble => {
            bubble.update(canvas.width, canvas.height);
            bubble.draw(ctx, glowIntensity);
        });
        
        const mainCtx = canvas.getContext('2d');
        mainCtx?.drawImage(offscreenCanvas.current, 0, 0);
        
        animationFrameId.current = requestAnimationFrame(animate);
    }, [theme, glowIntensity]);
    
    const handleResize = useCallback(() => {
        const canvas = canvasRef.current;
        if (!canvas) return;
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
        initBubbles(canvas.width, canvas.height);
    }, [initBubbles]);
    const isDark = useSelector((state: {
        theme: {
            flag: boolean
        }
    }) => state.theme.flag);
    useEffect(() => {
        offscreenCtx.current = offscreenCanvas.current.getContext('2d');
        handleResize();
        window.addEventListener('resize', handleResize);
        animationFrameId.current = requestAnimationFrame(animate);
        setTheme(isDark ? 'dark' : 'light');
        return () => {
            window.removeEventListener('resize', handleResize);
            if (animationFrameId.current) {
                cancelAnimationFrame(animationFrameId.current);
            }
        };
    }, [animate, handleResize, isDark]);
    
    return (
        <canvas
            ref={canvasRef}
            style={{
                position: 'fixed',
                top: 0,
                left: 0,
                zIndex: -1,
                transition: 'background 0.5s ease'
            }}
        />
    );
};

export default BubbleBackground;